<template>
  <div>
    <el-dialog
      :model-value="visible"
      :title="title"
      draggable
      width="900px"
      :show-close="false"
      :close-on-click-modal="false"
      class="voteOneDialog"
      @open="handleOpen"
      @close="mapClose"
      append-to-body
    >
      <div class="cont">
        <el-row class="mb-2">
          <el-col :span="8">
            <el-autocomplete
              v-model="locationParams.address"
              :fetch-suggestions="querySearch"
              placeholder="请输入详细地址"
              :trigger-on-focus="false"
              @select="handleSelect"
              value-key="title"
              clearable
            />
          </el-col>
          <el-col :span="4" :offset="1">
            <el-input v-model="locationParams.longitude" placeholder="经度" readonly />
          </el-col>
          <el-col :span="4" :offset="1">
            <el-input v-model="locationParams.latitude" placeholder="纬度" readonly />
          </el-col>

          <el-col :span="5" :offset="1">
            <div class="flex items-center justify-end">
              <el-button type="danger" @click="resultFn">确定</el-button>
              <el-button type="info" @click="mapClose">关闭</el-button>
            </div>
          </el-col>
        </el-row>
        <!-- 地图容器 -->
        <div id="map-container" class="w-full h-100 rounded border border-gray-200"></div>
      </div>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
  import { ref, nextTick, defineProps, defineEmits } from 'vue'
  import { ElMessage } from 'element-plus'

  let TMap = (window as any).TMap

  defineProps<{
    title: string
    visible: boolean
  }>()

  const emit = defineEmits(['getLocationSuccess', 'mapClose'])

  /**
   * 位置参数
   */
  const locationParams = ref<{
    longitude: number | null
    latitude: number | null
    address: string
  }>({
    longitude: null,
    latitude: null,
    address: ''
  })

  // 弹窗打开时初始化地图
  function handleOpen() {
    nextTick(() => {
      initMap()
    })
  }

  let map: any = null //不要要响应式，因为需要全局使用，会导致标记无法显示

  let markerLayer: any = null //不要要响应式，因为需要全局使用，会导致标记无法显示

  /**
   * 初始化地图
   */
  async function initMap() {
    const mapDom = document.getElementById('map-container')
    if (!mapDom) return

    // 如果地图已经初始化，则不进行初始化
    if (map) {
      return
    }

    await loadMapScript()

    TMap = (window as any).TMap

    // 根据地图类型设置不同的初始化参数
    const mapOptions: any = {
      center: new TMap.LatLng(locationParams.value.latitude, locationParams.value.longitude),
      zoom: 16
    }

    //初始化地图
    map = new TMap.Map(mapDom, mapOptions)

    //初始化marker图层
    markerLayer = new TMap.MultiMarker({
      id: 'marker-layer',
      map: map
    })

    // 绑定地图点击事件
    map.on('click', clickHandler)
  }

  /**
   * 搜索地址
   * @param queryString 搜索关键词
   * @param callback 回调函数
   */
  function querySearch(queryString: string, callback: (list: any[]) => void) {
    if (!queryString.trim()) {
      callback([])
      return
    }

    const url = 'https://apis.map.qq.com/ws/place/v1/suggestion'
    jsonp(url, {
      key: 'KQMBZ-GA7KW-AHZRP-YGKBA-WFS2S-TLFD4',
      keyword: queryString,
      output: 'jsonp'
    })
      .then((res: any) => {
        if (res.status == 0) {
          callback(res.data || [])
        } else {
          ElMessage.warning(res.message || '搜索失败')
          callback([])
        }
      })
      .catch((e: any) => {
        console.error('搜索错误：', e)
        ElMessage.error('搜索失败，请检查网络连接')
        callback([])
      })
  }

  /**
   * jsonp工具函数
   * @param url 请求地址
   * @param params 请求参数
   * @returns 返回Promise对象
   */
  function jsonp(url: string, params: Record<string, any>) {
    return new Promise((resolve, reject) => {
      const callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random())
      params.callback = callbackName
      const query = Object.keys(params)
        .map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
        .join('&')
      const script = document.createElement('script')
      script.src = url + (url.indexOf('?') === -1 ? '?' : '&') + query
      document.body.appendChild(script)
      ;(window as any)[callbackName] = function (data: any) {
        resolve(data)
        document.body.removeChild(script)
        delete (window as any)[callbackName]
      }
      script.onerror = function (e) {
        reject(e)
        document.body.removeChild(script)
        delete (window as any)[callbackName]
      }
    })
  }

  /**
   * 地图点击事件
   * @param evt 事件对象
   */
  function clickHandler(evt: any) {
    console.log(evt)
    const latitude = evt.latLng.getLat().toFixed(6)
    const longitude = evt.latLng.getLng().toFixed(6)

    locationParams.value.longitude = longitude
    locationParams.value.latitude = latitude

    // 如果有POI信息，更新地址
    if (evt.poi) {
      locationParams.value.address = evt.poi.name
    }

    // 更新标记位置
    updateMarkerPosition(latitude, longitude)
  }

  // 更新标记位置的专用函数
  function updateMarkerPosition(latitude: string, longitude: string) {
    // 如果标记层不存在，创建新的
    const isShow = markerLayer.geometries.find((item: any) => item.id === '1')
    if (isShow) {
      markerLayer.updateGeometries([
        {
          id: '1',
          position: new TMap.LatLng(latitude, longitude)
        }
      ])
    } else {
      console.log(markerLayer, '211212')
      markerLayer.add({
        id: '1',
        position: new TMap.LatLng(latitude, longitude),
        properties: {
          title: '当前位置'
        }
      })
    }

    // 平滑移动到新位置
    map.panTo(new TMap.LatLng(latitude, longitude))
  }

  /**
   * 确定按钮
   */
  function resultFn() {
    if (
      !locationParams.value.longitude ||
      !locationParams.value.latitude ||
      !locationParams.value.address
    ) {
      ElMessage.warning('请先选择位置')
      return
    }

    emit('getLocationSuccess', {
      longitude: locationParams.value.longitude,
      latitude: locationParams.value.latitude,
      address: locationParams.value.address
    })
  }

  /**
   * 关闭按钮
   */
  function mapClose() {
    emit('mapClose', false)
  }

  /**
   * 选择地址
   * @param item 选择地址
   */
  function handleSelect(item: any) {
    locationParams.value.address = item.title
    locationParams.value.longitude = item.longitude
    locationParams.value.latitude = item.latitude
  }

  /**
   * 初始化地图的经纬度，还有地址
   * @param options 经度，纬度，地址
   */
  function initMapLatLng(options: any) {
    if (options.longitude) {
      locationParams.value.longitude = options.longitude
    }
    if (options.latitude) {
      locationParams.value.latitude = options.latitude
    }
    if (options.address) {
      locationParams.value.address = options.address
    }
  }

  // 异步加载腾讯地图JS API
  function loadMapScript() {
    return new Promise<void>((resolve, reject) => {
      if ((window as any).TMap) {
        resolve()
        return
      }
      const script = document.createElement('script')
      script.type = 'text/javascript'
      script.src =
        'https://map.qq.com/api/gljs?v=1.exp&key=KQMBZ-GA7KW-AHZRP-YGKBA-WFS2S-TLFD4&callback=initMap'
      script.onload = () => {
        console.log('地图脚本加载成功')
        resolve()
      }
      script.onerror = () => {
        reject(new Error('地图脚本加载失败'))
      }
      document.body.appendChild(script)
    })
  }

  defineExpose({
    initMapLatLng
  })
</script>

<style scoped>
  /* 样式已使用 UnoCSS 类名编写 */
</style>
